import Setting from "./setting";
import UnitBox from "./unit/box";
import UnitPlayer from "./unit/player";
import MusicUtil from "./utils/music";

export interface GameData {
  position: number;
  type: number;
  time: number;
}

export default class Game {

  public setting = new Setting();

  private canvas: HTMLCanvasElement;
  constructor(canvas: HTMLCanvasElement) {
    if (!(canvas instanceof HTMLCanvasElement)) {
      throw new Error("构造游戏请使用[canvas]元素。");
    }
    this.canvas = canvas;
  }

  private unitBox: UnitBox = new UnitBox(this);
  public async loadData(loadFunc: (game: Game) => Promise<GameData[]>) {
    this.unitBox.setData(await loadFunc(this));
  }

  private isRun: boolean = false;
  public play() {
    this.isRun = true;
    this.drawExcute();
  }

  private drawExcute() {
    if (!this.isRun) { return; }
    requestAnimationFrame(() => {
      if (!this.isRun) { return; }
      this.drawAll();
      this.drawExcute();
    });
  }

  private player: UnitPlayer = new UnitPlayer(this);
  private drawAll() {
    const canvas = this.canvas;
    const context2D = canvas.getContext("2d");
    if (!context2D) { return; }
    context2D.clearRect(0, 0, canvas.width, canvas.height);
    this.drawSave((context2D) => {
      context2D.globalCompositeOperation = "destination-over";
      this.drawSave((context2D) => {
        context2D.translate(canvas.width / 2, canvas.height / 2)
        this.drawSave((context2D) => {
          this.player.drawExcute(context2D);
        });
        this.drawSave((context2D) => {
          this.unitBox.drawExcute(context2D);
        });
      });
      this.drawSave((context2D) => {
        context2D.fillStyle = "#cccccc";
        context2D.fillRect(0, 0, canvas.width, canvas.height);
      });
    });
  }

  public drawSave(drawFunc: (context2D: CanvasRenderingContext2D) => void) {
    const canvas = this.canvas;
    const context2D = canvas.getContext("2d");
    if (!context2D) { return; }
    context2D.save();
    drawFunc(context2D);
    context2D.restore();
  }

  public readonly music = new MusicUtil();
  public touch() {
    if (this.unitBox.targetAngle.OnRangeMiddle(this.player.angle.Angle, this.setting.judgmentRange)) {
      this.unitBox.next();
      this.player.next();
      if (this.unitBox.data.length === 1) {
        if (this.setting.onOverRePlay) {
          console.log("游戏完成");
          this.rePlay();
        } else {
          alert("游戏完成");
          this.isRun = false;
        }
      } else {
        this.music.play();
      }
    } else {
      if (this.setting.onErrorRePlay) {
        this.rePlay();
      } else {
        alert("游戏失败");
        this.isRun = false;
      }
    }
  }

  public rePlay() {
    this.isRun = true;
    this.setting = new Setting();
    this.player.rePlay();
    this.unitBox.rePlay();
  }

}
